package main

import (
	"fmt"
	"net/http"
	"os"

	"golang.org/x/net/html"
)

func main() {
	for _, url := range os.Args[1:] {
		outline(url)
	}
}

func outline(url string) error {
	resp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	doc, err := html.Parse(resp.Body)
	if err != nil {
		return err
	}

	forEachNode(doc, startElement, endElement)
	return nil
}

// 调用 pre(x) 和 post(x) 遍历以n为根的树中的每个节点x
// 两个函数都是可选的
// pre 在子节点被访问前调用（前序调用）
// post  在访问后调用（后续调用）
func forEachNode(n *html.Node, pre, post func(n *html.Node)) {
	if pre != nil {
		pre(n)
	}
	for c := n.FirstChild; c != nil; c = c.NextSibling {
		forEachNode(c, pre, post)
	}
	if post != nil {
		post(n)
	}
}

var depth int
var justStart bool

func startElement(n *html.Node) {
	if n.Type == html.ElementNode {
		if justStart {
			fmt.Println(">")
		}
		fmt.Printf("%*s<%s", depth*2, "", n.Data)
		if n.Data != "script" && n.Data != "style" {
			for _, attr := range n.Attr {
				fmt.Printf(` %s="%s"`, attr.Key, attr.Val)
			}
		}
		justStart = true
		depth++
	}
}

func endElement(n *html.Node) {
	if n.Type == html.ElementNode {
		depth--
		if justStart {
			fmt.Println("/>")
			justStart = false
		} else {
			fmt.Printf("%*s</%s>\n", depth*2, "", n.Data)
		}
	}
}
